package demo03;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo04Lock {
    public static void main(String[] args) {
        Runnable sellTicket = new Runnable() { // 布置线程任务：售100张票
            private int ticket = 100; // 票总数100张
            Lock lock = new ReentrantLock(); // 创建锁对象，Lock为接口，因此使用其子类ReentrantLock创建

            @Override
            public void run() { // 每个线程开始任务的起点
                while (true) { // 无限循环，窗口一直开放
                    /*
                     *  在判断语句之前，使用Lock的实现类对象加锁
                     *  第一个抢到优先权的线程抢到这把锁，进入加锁~释放锁之间执行语句，其他线程只能在外面等着
                     *  线程在执行到释放锁语句后，将锁继续给优先权高的线程，然后重新加锁，执行加锁~释放锁之间的语句
                     *  如此往复，加锁~释放锁之间的代码就只会有一条线程在执行，防止了线程安全问题
                     */
                    lock.lock(); // 加锁
                    
                    if (ticket > 0) { // 票数大于0，代表有票可售，进行售票
                        try { // 模拟出票时间
                            Thread.sleep(50);
                            System.out.println(Thread.currentThread().getName() + "正在卖：" + ticket--); // 售1张票
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally { // 无论程序是否异常，都会执行释放锁，提高程序效率
                            lock.unlock(); // 释放锁
                        }
                    }
                }
            }
        };

        // 开启三个线程：三个窗口
        new Thread(sellTicket, "窗口1").start();
        new Thread(sellTicket, "窗口2").start();
        new Thread(sellTicket, "窗口3").start();

        /*
         *  输出结果：各个窗口交替输出，输出的内容按顺序从100~1
         */
    }
}
